﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Deflection
{
    class SuperEnemy : Enemy
    {
        public List<Enemy> enemies = new List<Enemy>();
        public List<Vector3> offset = new List<Vector3>();
        public Vector2 size = new Vector2();
        public Enemy core;
        public bool allEnemiesInPlace = false;
        public bool allEnemiesAlive = false;
        public bool allEnemiesDead = false;
        int centerColomnSize = 0;
        int sideColomnSize = 0;

        public SuperEnemy(Vector2 Position)  : base(Position)
        {
            Type = EnemyType.SuperSquare;
        }

        public SuperEnemy(Vector2 position, List <Enemy> enemies, Vector2 size, Texture2D texture)  : base(position, texture, Color.Red)
        {
            this.alive = true;
            this.position = position;
            this.size = size;
            this.enemies = enemies;
            this.Type = EnemyType.SuperSquare;


            Enemy.EnemyType eType;
            if (enemies.Count() == 0)
            {
                eType = EnemyType.SquareEnemy;
            }
            else
            {
                eType = enemies[0].Type;
                if (eType == EnemyType.TriangleEnemy)
                {
                    Type = EnemyType.SuperTriangle;
                }
                else if (eType == EnemyType.SquareEnemy)
                {
                    Type = EnemyType.SuperSquare;
                }
                else if (eType == EnemyType.HexagonEnemy)
                {
                    Type = EnemyType.SuperHexagon;
                }
            }
            switch (eType)
            {
                case EnemyType.SquareEnemy:
                    Vector2 midPoint = new Vector2((int)size.X/2, (int)size.Y/2);
                    // Console.WriteLine(midPoint.ToString());
                    for (int i = 0; i < size.Y; i++)
                    {
                        for (int j = 0; j < size.X; j++)
                        {
                            Vector2 tempOff = new Vector2(0, 0);
                            Vector2 currentPos = new Vector2(j, i);
                            tempOff = currentPos - midPoint; // 1 1 center
                            tempOff.X = tempOff.X * Texture.Width;
                            tempOff.Y = tempOff.Y * Texture.Height;

                            offset.Add(new Vector3(tempOff,0));
                        }
                    }
                    break;
                case EnemyType.SuperSquare:
                    break;

                case EnemyType.TriangleEnemy:
                    #region TriangleEnemy

                    // Build the superTriangle
                    int baseSize = 5;

                    float baseYOffset = Texture.Height;
                    float baseXOffset = Texture.Height / 2;
                    float smallYOffset = 0f;

                    // find row with core
                    int a = (int)Math.Round((float)baseSize / 2);
                    int b = (int)Math.Round((float)a / 2);
                    int coreRowIndex = a + b;


                    for (int row = 0; row < 5; row++)
                    {
                        // ((row * 2) + 1) is the number of triangles for that row, (row number x2) + 1
                        int trianglesInRow = ((row * 2) + 1);

                        // find row middle triangle index
                        int middleIndex = row;

                        for (int tri = 0; tri < trianglesInRow; tri++)
                        {
                            // X offset
                            // Find difference in current row triangle and the rows middle triangle index
                            int xDifference = middleIndex - tri;

                            // Y offset
                            // Find difference between center row (core row) and current row
                            int yDifference = coreRowIndex - row;

                            // ( positive y = down )
                            float yOffset = (-yDifference * baseYOffset);

                            float rotation = 0;
                            // triangle Up or down?
                            if (tri % 2 == 0)
                            {
                                // even so up
                                // + a small offset
                                yOffset += smallYOffset;
                                // triangle.SpriteOrientation = Up;
                                rotation = 0;
                            }
                            else
                            {
                                // odd so down
                                // - a small offset
                                yOffset -= smallYOffset;
                                // triangle.SpriteOrientation = Down;
                                rotation = (float)Math.PI;
                            }

                            float xOffset = (xDifference * baseXOffset);

                            offset.Add(new Vector3(xOffset, yOffset, rotation));
                            

                        }
                    }                  
                    break;
                    #endregion TriangleEnemy
                case EnemyType.HexagonEnemy:
                    #region HexagonEnemy

                    float baseYOffsetHex = Texture.Height - 4;
                    float baseXOffsetHex = Texture.Height * 0.75f;

                    centerColomnSize = 5;
                    sideColomnSize = (centerColomnSize + 1) / 2;

                   // --------------------------------------

                    float xOffsetHex = 0;
                    float yOffsetHex = 0;

                    // left to center
                    for (int c = sideColomnSize; c <= centerColomnSize; c++)
                    {
                        // Add y offset based on column number
                        // eg first column on the left offset = (5 - 3) * (32 / 2) = 32 pixels
                        yOffsetHex = (centerColomnSize - c) * (baseYOffsetHex / 2);
                        // Add 75% of hexagon width worth of x offset
                        xOffsetHex += baseXOffsetHex;
                        
                        for (int h = 0; h < c; h++)
                        {
                            // Add a image/hexagon height worth of y offset
                            yOffsetHex += baseYOffsetHex;
                            offset.Add(new Vector3(xOffsetHex, yOffsetHex, 0));
                        }
                    }
                    // center to right
                    for (int c = centerColomnSize - 1; c >= sideColomnSize; c--)
                    {
                        // Add y offset based on column number
                        yOffsetHex = (centerColomnSize - c) * (baseYOffsetHex / 2);
                        // Add 75% of hexagon width worth of x offset
                        xOffsetHex += baseXOffsetHex;

                        for (int h = 0; h < c; h++)
                        {
                            // Add a image/hexagon height worth of y offset
                            yOffsetHex += baseYOffsetHex;
                            offset.Add(new Vector3(xOffsetHex, yOffsetHex, 0));
                        }
                    }


                    break;
                    #endregion HexagonEnemy
                default:
                    break;
            }
        }

        public override void Update(GameTime gameTime)
        {
            /*switch (State)
            {
                case EnemyState.Spawning:

                    State = EnemyState.Alive;

                    break;
                case EnemyState.Alive:

                    if (core != null && !core.Alive)
                    {
                        State = EnemyState.Dying;
                        Die();
                    }

                    UpdateSubEnemiesPositions();

                    break;
                case EnemyState.Dying:


                    break;
                case EnemyState.Dead:
                    break;
            }*/


            if (core != null && core.State != EnemyState.Alive)
            {
                Die();
            }
            UpdateSubEnemiesPositions();
            if (allEnemiesDead)
            {
                Die();
            }
            // make the enemy move to the left slowly
            velocity.X = -GameParameters.BASE_ENEMY_SPEED / 2;
            //Position -= new Vector2(GameParameters.BASE_ENEMY_SPEED / 2, 0);

            // Enemy is 'on' the target so create a new one
            if (HasPath())
            {
                // give it a move target to go to
                this.movementTarget = path.position + (path.GetCurrentPositionOnPath() * path.scale);
                Console.WriteLine(path.CurrentNodeIndex);
                // get the next the path index
                pathNodeIndex = path.Next(pathNodeIndex);
            }
            else
            {
                this.movementTarget = CreateMovementTarget();

            }

            base.Update(gameTime);
        }

        private void UpdateSubEnemiesPositions()
        {
            int count = 0;
            Vector2 midPoint = new Vector2(0, 0);
            if (this.Type == EnemyType.SuperHexagon)
            {
                midPoint.X = sideColomnSize * (Texture.Height * 0.75f);
                midPoint.Y = sideColomnSize * (Texture.Height - 4);
            }
            allEnemiesInPlace = false;
            allEnemiesAlive = false;
            allEnemiesDead = false;

            // Loop through all enemies
            while (count < enemies.Count() && count < offset.Count())
            {
                // Find the enemies position in the super enemy
                Vector2 targetPos = Position + new Vector2(offset[count].X, offset[count].Y);
                
                // Check if the enemy is nearly at its position
                if (GetDistance(enemies[count].Position, targetPos) > 3.0f)
                {
                    // find the direction towards its target
                    enemies[count].FindDirection(targetPos);

                    enemies[count].Velocity = Vector2.Lerp(enemies[count].Velocity, enemies[count].direction, 0.2f);

                    // make the enemy rotate slowly to the right orientation // 0.025 or 0.05 is good
                    enemies[count].Rotation = MathHelper.Lerp(enemies[count].Rotation, offset[count].Z, 0.025f);

                }
                else
                {
                    enemies[count].Rotation = offset[count].Z;
                    enemies[count].position = targetPos;
                    enemies[count].Velocity = Velocity;
                    enemies[count].inPlace = true;
                    allEnemiesAlive = enemies.All(enemy => enemy.State == EnemyState.Alive);
                    allEnemiesInPlace = enemies.All(enemy => enemy.inPlace);
                    allEnemiesDead = enemies.All(enemy => enemy.State != EnemyState.Alive);
                    // Check that
                    if (new Vector2(offset[count].X, offset[count].Y) == midPoint && allEnemiesInPlace && allEnemiesAlive && !allEnemiesDead)
                    {
                enemies.ForEach(delegate(Enemy e)
                {
                    e.IsCollidable = true;
                });
                        core = enemies[count];
                    }
                }

                count++;
            }
            if (core != null)
            {
                core.isCore = true;
            }
        }
        public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            /*if (alive)
            {
                spriteBatch.Draw(Enemy.EnemySprite, position, Color.White);
            }*/
        }
        public override bool IsOffscreen()
        {
            return base.IsOffscreen();
        }
        public override void Die()
        {
            int count = 0;
            foreach (Enemy enemy in enemies)
            {
                enemy.partOfSuper = false;
                if (enemy.State == EnemyState.Alive)
                {
                    // So super enemy doesnt explode  when it reaches the left side of the screen
                    if (this.position.X > 1)
                    {
                        // Make the enemy explode outwards
                        Random rand = new Random((int)enemy.position.X * (int)enemy.position.Y);
                        float r = (float)rand.NextDouble();
                        r = r * rand.Next(-5, 6);
                        Vector2 explodingVelocity = this.position - enemy.position;
                        if (this.Type == EnemyType.SuperHexagon)
                        {
                            Vector2 midPoint = new Vector2(0, 0);
                            midPoint.X = sideColomnSize * (Texture.Height * 0.75f);
                            midPoint.Y = sideColomnSize * (Texture.Height - 4);
                            explodingVelocity = (this.position + midPoint) - enemy.position;
                        }
                        explodingVelocity.Normalize();
                        explodingVelocity = Vector2.Multiply(explodingVelocity, GameParameters.BASE_ENEMY_SPEED * 3);
                        explodingVelocity = Vector2.Add(explodingVelocity, new Vector2(r, r));
                        enemy.Velocity = -explodingVelocity;

                        // If the enemy is not the core, make it into a projectile
                        if (!enemy.isCore)
                        {
                            // clever :)
                            EnemyFactory.Instance().Enemies.Remove(enemy);
                            ProjectileFactory.Instance().projectiles.Add(enemy);
                            if (core.killer != null)
                            {
                                enemy.player = core.killer;
                            }
                        }
                    }
                }
                count++;
            }
            enemies.Clear();
            base.Die();
        }

    }
}
